/*
 * Файл args_pass.c
 *
 * Програма створює 4 потоки за допомогою процедури pthread_create() 
 * і знаходить суму чисел від 0 до 100.
 * Кожен потік друкує повідомлення «Hello World!», а тоді завершується 
 * зверненням до процедури pthread_exit(). 
 * 
 * Компіляція 
 * gcc -pthread args_pass.c -Wall --pedantic -o args_pass
 * 
 * Виконання
 * ./second
 *
 */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

// задається кількість потоків
#define NUM_THREADS     4 

// задається верхнє значення діапазону чисел
#define MAX_RANGE     100

/**
 * Опис структури даних для передачі її в потік
 * Елементами структури є
 *  thread_id - ідентифікатор потоку
 *  fromVal, toVal - значення діапазону чисел 
 *  (від якого до якого буде отримуватись сума чисел)
 */
struct thread_data
{
   long	thread_id;
   long fromVal;
   long toVal;
   long sum;
};
// Оголошення масиву структур даних, елементи якого будуть опрацьовуватись потоками
struct thread_data td[NUM_THREADS];
/**
 * Функція, яка викликається кожним потоком і обчислює суму чисел 
 * Здійснюється передача аргументів за адресою (не за значенням!)
 * Аргументом функції є структура даних
 */
void *getPartialSum(void *threadarg)
{
   long tid, tfromVal, ttoVal,tsum; 
   int i;
   struct thread_data *my_tdata;
   my_tdata = (struct thread_data *) threadarg;
// Нагадування: операція "стрілка" використовується для звертання до поля структури даних, що задана через вказівник на цю структуру
   tid = my_tdata->thread_id;  
   tfromVal = my_tdata->fromVal;
   ttoVal = my_tdata->toVal;
   tsum = my_tdata->sum;
   for(i=tfromVal;i<ttoVal;i++)
   {
   tsum+= i; 
   }

   printf("thread #%ld,fromVAl %ld, toVAl %ld, sum %ld!\n", tid,tfromVal, ttoVal,tsum);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t, step;
   step=MAX_RANGE/NUM_THREADS;

   for(t=0; t<NUM_THREADS; t++)
   { 
// Нагадування: операція "крапка" використовується для звертання до поля структури даних, що задана через змінну
	   td[t].thread_id=t;
	   td[t].sum=0;
	   td[t].fromVal=(t==0?t:td[t-1].fromVal+step);
	   td[t].toVal=(t==0?step:td[t-1].toVal+step);

      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, getPartialSum, (void *)&td[t]);

      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }

   /* Last thing that main() should do */
   pthread_exit(NULL);
}
